﻿using System;
using System.Windows.Forms;

namespace Nuciferati.Forms
{
	/// <summary>
	/// A class to emulate the fixed dialogs in windows 7 (thick bordered, unsizable)
	/// </summary>
	public class UnsizableForm : Form
	{
		#region Constructors

		/// <summary>
		/// Initializes the properties of an unsizable form
		/// </summary>
		public UnsizableForm()
		{
			// Hide the grips
			this.SizeGripStyle = SizeGripStyle.Hide;

			// Subscribe the form's load event
			this.Shown += new EventHandler( UnsizableForm_Shown );
			this.Load += new EventHandler( UnsizableForm_Load );
		}

		#endregion

		#region Control Events

		/// <summary>
		/// An event that is raised when the form is shown
		/// </summary>
		/// <param name="sender">Unused</param>
		/// <param name="e">Unused</param>
		private void UnsizableForm_Shown( object sender, EventArgs e )
		{
			// Center the form when it's shown
			this.CenterToParent();
		}

		/// <summary>
		/// An event that is raised when the form is loaded
		/// </summary>
		/// <param name="sender">Unused</param>
		/// <param name="e">Unused</param>
		private void UnsizableForm_Load( object sender, EventArgs e )
		{
			// Center the form when it's opened
			this.CenterToParent();
		}

		#endregion

		#region Override Events

		/// <summary>
		/// Override the windows procedure to stop resizing
		/// </summary>
		/// <param name="m">The windows message being sent to the control</param>
		protected override void WndProc( ref Message m )
		{
			// Call the base window procedure
			base.WndProc( ref m );

			switch ( m.Msg )
			{
				case WM_NCHITTEST:

					// Get the HitTest result
					var result = (HitTest)m.Result.ToInt32();

					// Change it to what we want it to be
					switch ( result )
					{
						case HitTest.Left:
						case HitTest.BottomLeft:
						case HitTest.Bottom:
						case HitTest.BottomRight:
						case HitTest.Right:
							m.Result = new IntPtr( (int)HitTest.Nowhere );
							break;

						case HitTest.TopLeft:
						case HitTest.Top:
						case HitTest.TopRight:
							m.Result = new IntPtr( (int)HitTest.Caption );
							break;
					}

					break;
			}
		}

		#endregion

		#region Private Constants

		/// <summary>
		/// A Windows API constant
		/// </summary>
		private const int WM_NCHITTEST = 0x00000084;

		#endregion
	}

	/// <summary>
	/// The different locations a hover can hover over for the WM_NCHITTEST message
	/// </summary>
	enum HitTest
	{
		Caption = 2,
		Transparent = -1,
		Nowhere = 0,
		Client = 1,
		Left = 10,
		Right = 11,
		Top = 12,
		TopLeft = 13,
		TopRight = 14,
		Bottom = 15,
		BottomLeft = 16,
		BottomRight = 17,
		Border = 18
	}
}
